

package com.hazelcast.test.starter.answer;

import com.hazelcast.internal.namespace.impl.NoOpUserCodeNamespaceService;
import com.hazelcast.spi.impl.NodeEngine;
import com.hazelcast.spi.impl.operationservice.impl.OperationServiceImpl;
import org.mockito.invocation.InvocationOnMock;

import static org.mockito.Mockito.mock;

/**
 * Default {@link org.mockito.stubbing.Answer} to create a mock for a proxied
 * {@link NodeEngine}.
 */
public class NodeEngineAnswer extends AbstractAnswer {

    private Object ucnService;

    public NodeEngineAnswer(Object delegate) {
        super(delegate);
    }

    @Override
    Object answer(InvocationOnMock invocation, String methodName, Object[] arguments) throws Exception {
        if (arguments.length == 1 && methodName.equals("getLogger")) {
            return getLogger(arguments);
        } else
            if (arguments.length == 1 && methodName.equals("getService")) {
                Object service = invokeForMock(invocation, arguments);
                return createMockForTargetClass(service, new ServiceAnswer(service));
            } else
                if (arguments.length == 0 && methodName.equals("getNamespaceService")) {
                    if (ucnService == null) {
                        try {
                            ucnService = invoke(invocation);
                        } catch (NoSuchMethodException ignored) {
                            // <5.4.0 compatability tests support, since UCN code is used internally a lot, even if UCN is not enabled
                            ucnService = mock(NoOpUserCodeNamespaceService.class);
                        }
                    }
                    return ucnService;
                } else
                    if (arguments.length == 0 && methodName.equals("getOperationService")) {
                        Object operationService = invokeForMock(invocation);
                        return mock(OperationServiceImpl.class, new OperationServiceAnswer(operationService));
                    } else
                        if (arguments.length == 0 && methodName.equals("getConfigClassLoader")) {
                            return targetClassloader;
                        } else
                            if (arguments.length == 0 && methodName.equals("getSplitBrainMergePolicyProvider")) {
                                Object provider = invokeForMock(invocation, arguments);
                                return createMockForTargetClass(provider, new DelegatingAnswer(provider));
                            } else
                                if (arguments.length == 0 && (methodName.startsWith("get") || methodName.startsWith("is"))) {
                                    return invoke(invocation);
                                }
        throw new UnsupportedOperationException("Method is not implemented in NodeEngineAnswer: " + methodName);
    }
}
